<?php

namespace maotool\office\xlsx;

use maotool\core\request\ExportParam;
use maotool\core\request\PageParam;
use maotool\log\Console;
use maotool\object\ObjUtil;
use maotool\util\ArrayUtil;

/**
 * Excel工作表数据处理类
 * 
 * 该类用于处理Excel工作表的各种数据结构，包括标题、头部信息、原始数据、
 * 列表数据、树形数据和表格数据等。支持数据分页加载和字段映射功能。
 * 
 * 使用示例：
 * ```
 * $sheet = new Sheet();
 * $sheet->setTitle('用户数据');
 * $sheet->setHeader(['姓名', '年龄', '邮箱']);
 * $sheet->setData($userData);
 * ```
 */
class Sheet
{

    /**
     * 工作表标题
     * 
     * 用于标识当前工作表的名称，通常显示在Excel工作表标签上
     * 
     * @var string
     */
    public $title;

    /**
     * 头部信息
     * 
     * 包含工作表的列标题和格式定义，通常是字符串数组
     * 
     * @var array
     */
    protected $header;

    /**
     * 原始数据
     * 
     * 存储未经处理的原始数据，可以是任意格式的数据集合
     * 
     * @var array
     */
    protected $data;

    /**
     * 列表数据
     * 
     * 适用于一维数组结构的数据展示，通常是从数据库查询的结果集
     * 
     * @var array
     */
    protected $list;

    /**
     * 树数据
     * 
     * 适用于具有层级关系的数据组织，如组织架构、分类目录等
     * 
     * @var array
     */
    protected $tree;

    /**
     * 表格数据
     * 
     * 适用于二维表格结构的数据展示，每个元素代表一行数据
     * 
     * @var array
     */
    protected $table;

    /**
     * 映射器
     * 
     * 用于定义数据字段与显示字段之间的映射关系，实现数据转换
     * 
     * @var array
     */
    protected $mapper;

    /**
     * 初始化Sheet对象，设置各属性的默认值
     * 
     * 所有数据容器初始化为空数组
     */
    public function __construct()
    {
        $this->header = [];
        $this->mapper = [];
        $this->data = [];
        $this->list = [];
        $this->tree = [];
        $this->table = [];
    }

    /**
     * 获取头部信息
     * 
     * @return array 头部信息数组
     */
    public function getHeader()
    {
        return $this->header;
    }

    /**
     * 设置头部信息
     * 
     * @param array $header 头部信息数组
     * @return void
     */
    public function setHeader($header)
    {
        $this->header = $header;
    }

    /**
     * 获取原始数据
     * 
     * @return array 原始数据数组
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * 设置原始数据
     * 
     * @param array $data 原始数据数组
     * @return void
     */
    public function setData($data)
    {
        $this->data = $data;
    }

    /**
     * 添加单条原始数据
     * 
     * @param mixed $item 单条数据项
     * @return void
     */
    public function addData($item)
    {
        $this->data[] = $item;
    }

    /**
     * 获取表格数据
     * 
     * @return array 表格数据数组
     */
    public function getTable()
    {
        return $this->table;
    }

    /**
     * 设置表格数据
     * 
     * @param array $table 表格数据数组
     * @return void
     */
    public function setTable($table)
    {
        $this->table = $table;
    }

    /**
     * 添加单条表格数据
     * 
     * @param mixed $item 单条表格数据项
     * @return void
     */
    public function addTable($item)
    {
        $this->table[] = $item;
    }

    /**
     * 获取列表数据
     * 
     * @return array 列表数据数组
     */
    public function getList()
    {
        return $this->list;
    }

    /**
     * 设置列表数据
     * 
     * @param array $list 列表数据数组
     * @return void
     */
    public function setList($list)
    {
        $this->list = $list;
    }

    /**
     * 添加单条列表数据
     * 
     * @param mixed $item 单条列表数据项
     * @return void
     */
    public function addList($item)
    {
        $this->list[] = $item;
    }

    /**
     * 获取树形数据
     * 
     * @return array 树形数据数组
     */
    public function getTree()
    {
        return $this->tree;
    }

    /**
     * 设置树形数据
     * 
     * @param array $tree 树形数据数组
     * @return void
     */
    public function setTree($tree)
    {
        $this->tree = $tree;
    }

    /**
     * 添加单条树形数据
     * 
     * @param mixed $item 单条树形数据项
     * @return void
     */
    public function addTree($item)
    {
        $this->tree[] = $item;
    }

    /**
     * 获取工作表标题
     * 
     * @return string 工作表标题
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * 设置工作表标题
     * 
     * @param string $title 工作表标题
     * @return void
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * 分页获取数据
     * 
     * 通过回调函数逐页获取数据，直到所有分页数据加载完成。
     * 每次获取一页数据后会合并到当前列表中，并输出调试日志。
     * 
     * @param callable $next 数据获取回调函数，接收PageParam参数并返回结果
     * @param ExportParam|null $exportParam 导出参数配置，包含分页信息和查询参数
     * @return void
     */
    public function pagination($next, $exportParam = null)
    {
        $isHasNextPage = true;
        if (ObjUtil::isNull($exportParam)) {
            $exportParam = new ExportParam();
        }
        $pageNo = $exportParam->getPageNo();
        $pageTotal = 0;
        while ($isHasNextPage) {
            $pageParam = new PageParam();
            $pageParam->setPageNo($pageNo);
            $pageParam->setPageSize($exportParam->getPageSize());
            $pageParam->setParam($exportParam->getParam());
            $exportResult = $next($pageParam);
            $this->setList(ArrayUtil::merge($this->getList(), $exportResult->getList()));
            $isHasNextPage = $exportResult->isHasNextPage();
            $pageTotal = $pageTotal + $exportResult->getSize();
            Console::debug("Xlsx 分页数据加载中 当前是第 " . $pageNo . " 分片 分片数据数量 " . $exportResult->getSize() . " 总数量:" . $pageTotal);
            if ($isHasNextPage) {
                ++$pageNo;
            }
        }
        Console::debug("Xlsx 分页数据加载完成 当前是第 " . $pageNo . " 分片  总数量:" . $pageTotal);
    }

    /**
     * 获取映射器
     * 
     * @return array 映射器数组
     */
    public function getMapper()
    {
        return $this->mapper;
    }

    /**
     * 设置映射器
     * 
     * @param array $mapper 映射器数组
     * @return void
     */
    public function setMapper($mapper)
    {
        $this->mapper = $mapper;
    }

}